package graph;

import java.io.Serializable;
import java.util.*;

/**
 * This is the superclass of all Nodes classes
 *
 */

public abstract class Node implements Serializable
{

	/**
	 * Converts a tree with node as root into the Dot language.
	 * @param node
	 * @return
	 */
	public static String toDotLanguage(Node node)
	{
		StringBuilder result = new StringBuilder();
		result.append("Digraph G {\n");
		result.append(toDotLanguage2(node,0));
		result.append("}");
		
		return result.toString();
	}

	/**
	 * Helper method for toDotLanguage();
	 * 
	 * @param node
	 * @param parentID
	 * @return
	 */
	private static String toDotLanguage2(Node node, long parentID)
	{
		StringBuilder result = new StringBuilder();
		Calendar c = Calendar.getInstance();
		Random r = new Random();
		
		long ID = Math.abs(c.getTimeInMillis() + r.nextLong());
		String label = node.toString();
		
		if((node instanceof ValueNode) && !(node instanceof LiteralNode))
		{
			ValueNode vn = (ValueNode)node;
			if(vn.isValidValue())
			{
				if(vn instanceof IntValueNode)
				{
					int value = ((IntValueNode)vn).getValue();
					result.append(ID + " [label=\"" + label + "," + value + "\"];" + "\n");
				}
				else
				{
					boolean value = ((BoolValueNode)vn).getValue();
					result.append(ID + " [label=\"" + label + "," + value + "\"];" + "\n");
				}
			}
			else
				result.append(ID + " [label=\"" + label + "\"];" + "\n");
		}
		else
			result.append(ID + " [label=\"" + label + "\"];" + "\n");
		
		result.append(parentID + " -> " + ID + ";" + "\n");
		
		if(node instanceof OperatorNode)
		{
			OperatorNode temp = (OperatorNode)node;
			result.append(toDotLanguage2(temp.getLeftOperand(),ID));
			result.append(toDotLanguage2(temp.getRightOperand(),ID));
		}
		else if(node instanceof BlockNode)
		{
			BlockNode temp = (BlockNode)node;
			Iterator<Node> it = temp.iterator();
			while(it.hasNext())
				result.append(toDotLanguage2(it.next(),ID));
		}
		else if(node instanceof IfNode)
		{
			IfNode temp = (IfNode)node;
			result.append(toDotLanguage2((Node)temp.getConditionNode(),ID));
			if(temp.getThenNode()!=null)
				result.append(toDotLanguage2(temp.getThenNode(),ID));
			if(temp.getElseNode()!=null)
				result.append(toDotLanguage2(temp.getElseNode(),ID));
		}
		else if(node instanceof WhileNode)
		{
			WhileNode temp = (WhileNode)node;
			result.append(toDotLanguage2((Node)temp.getConditionNode(),ID));
			result.append(toDotLanguage2(temp.getDoNode(),ID));
		}
		else if(node instanceof AssignNode)
		{
			AssignNode temp = (AssignNode)node;
			result.append(toDotLanguage2(temp.getVariableNode(),ID));
			result.append(toDotLanguage2(temp.getValueNode(),ID));
		}
		
		return result.toString();
	}

}